package com.chenfan.filestore.config;

import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.chenfan.ccp.common.result.R;
import com.chenfan.infra.context.TenantContextHolder;
import com.chenfan.print.api.PrintClient;
import com.chenfan.print.vo.BaseDatabaseVO;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 * @author leo
 */
@Slf4j
@Component
public class DynamicDataSourceRegister implements ImportBeanDefinitionRegistrar, EnvironmentAware
//        , ApplicationListener<ApplicationReadyEvent>
{

    /**
     * 指定默认数据源(springboot2.0默认数据源是hikari如何想使用其他数据源可以自己配置)
     */
    private static final String DATASOURCE_TYPE_DEFAULT = "com.zaxxer.hikari.HikariDataSource";

    /**
     * 默认数据源
     */
    private DataSource defaultDataSource;

    public DataSource getDefaultDataSource() {
        return defaultDataSource;
    }

    public void setDefaultDataSource(DataSource defaultDataSource) {
        this.defaultDataSource = defaultDataSource;
    }

    /**
     * 用户自定义数据源
     */
    private Map<String, DataSource> customDataSources  = new HashMap<>();

    /**
     * 加载多数据源配置
     * @param env
     */
    @Override
    public void setEnvironment(Environment env) {
        initDefaultDataSource(env);
//        initCustomDataSources(env);
    }





    /**
     * 初始化主数据源
     * @param env
     */
    private void initDefaultDataSource(Environment env) {
        // 读取主数据源
        Map<String, Object> dsMap = new HashMap<>();
        dsMap.put("driver", env.getProperty("spring.datasource.driver-class-name"));
        dsMap.put("url", env.getProperty("spring.datasource.url"));
        dsMap.put("username", env.getProperty("spring.datasource.username"));
        dsMap.put("password", env.getProperty("spring.datasource.password"));
        defaultDataSource = buildDataSource(dsMap);
    }


    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        Map<Object, Object> targetDataSources = new HashMap<Object, Object>(16);
        // 将主数据源添加到更多数据源中
        targetDataSources.put(DS.MAIN, defaultDataSource);
        DynamicDataSourceContextHolder.DS_KEYS.add(DS.MAIN);
        // 添加更多数据源
        targetDataSources.putAll(customDataSources);
        DynamicDataSourceContextHolder.DS_KEYS.addAll(customDataSources.keySet());

        // 创建DynamicDataSource
        GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClass(DynamicDataSource.class);
        beanDefinition.setSynthetic(true);
        MutablePropertyValues mpv = beanDefinition.getPropertyValues();
        mpv.addPropertyValue("defaultTargetDataSource", defaultDataSource);
        mpv.addPropertyValue("targetDataSources", targetDataSources);
        // 注册到Spring容器中
        registry.registerBeanDefinition("dataSource1", beanDefinition);
        log.info("Dynamic DataSource Registry");
    }

    /**
     * 创建DataSource
     * @param dsMap
     * @return
     */
    public DataSource buildDataSource(Map<String, Object> dsMap) {
        try {
            Object type = dsMap.get("type");
            if (type == null){
                //默认DataSource
                type = DATASOURCE_TYPE_DEFAULT;
            }

            Class<? extends DataSource> dataSourceType;
            dataSourceType = (Class<? extends DataSource>)Class.forName((String)type);
            System.out.println(dsMap);
            String driverClassName = dsMap.get("driver").toString();
            String url = dsMap.get("url").toString();
            String username = dsMap.get("username").toString();
            String password = dsMap.get("password").toString();
            // 自定义DataSource配置
            DataSource build = DataSourceBuilder.create().driverClassName(driverClassName)
                    .url(url).username(username).password(password).type(dataSourceType)
                    .build();
            HikariConfig hikariConfig = new HikariConfig();
            hikariConfig.setDataSource(build);
            hikariConfig.setMaximumPoolSize(300);
            return new HikariDataSource(hikariConfig);

        }catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    @PostConstruct
    public void refreshDB(){
        DynamicDataSource dynamicDataSource = SpringUtil.getBean(DynamicDataSource.class);
        R<List<BaseDatabaseVO>> listR = SpringUtil.getBean(PrintClient.class).findAll();
        List<BaseDatabaseVO> databases = listR.getObj();
        log.info("数据库信息为{}",JSONUtil.toJsonStr(databases));
        customDataSources.clear();
        databases.forEach(baseDatabase -> {
            //读取主数据源new StringBuilder("").append(baseDatabase.getIp())
            String url = String.format("jdbc:mysql://%s:%s/%s?%s",baseDatabase.getHost(),baseDatabase.getPort(),baseDatabase.getDbName(),baseDatabase.getUrl());
            Map<String, Object> dsMap = new HashMap<>(16);
            dsMap.put("driver", baseDatabase.getDriver());
            dsMap.put("url", url);
            dsMap.put("username", baseDatabase.getUserName());
            dsMap.put("password", baseDatabase.getPassword());
            DataSource customDatabase = buildDataSource(dsMap);
            customDataSources.put(baseDatabase.getDatabaseId()+"",customDatabase);
        });

        dynamicDataSource.updateTargetDataSource(defaultDataSource,customDataSources);
        DynamicDataSourceContextHolder.DS_KEYS.clear();
        DynamicDataSourceContextHolder.DS_KEYS.add(DS.MAIN);
        DynamicDataSourceContextHolder.DS_KEYS.addAll(customDataSources.keySet());
    }


    /**
     * 初始化更多数据源
     * @param env
     */
    private void initCustomDataSources(Environment env) {

//        // 读取主数据源
//        Map<String, Object> dsMap = new HashMap<>(16);
//        dsMap.put("driver", env.getProperty("spring.datasource.driver-class-name"));
//        dsMap.put("url", "jdbc:mysql://10.228.81.19:38309/eop_baseinfo_test?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2B8");
//        dsMap.put("username", env.getProperty("spring.datasource.username"));
//        dsMap.put("password", env.getProperty("spring.datasource.password"));
//        DataSource salve = buildDataSource(dsMap);
//
//        customDataSources.put("slave",salve);
        // 读取配置文件获取更多数据源
//        String dsPrefixs = env.getProperty("custom.datasource.names");
//        for (String dsPrefix : dsPrefixs.split(",")) {
//            // 多个数据源
//            Map<String, Object> dsMap = new HashMap<>();
//            dsMap.put("driver", env.getProperty("custom.datasource." + dsPrefix + ".driver-class-name"));
//            dsMap.put("url", env.getProperty("custom.datasource." + dsPrefix + ".url"));
//            dsMap.put("username", env.getProperty("custom.datasource." + dsPrefix + ".username"));
//            dsMap.put("password", env.getProperty("custom.datasource." + dsPrefix + ".password"));
//            DataSource ds = buildDataSource(dsMap);
//            customDataSources.put(dsPrefix, ds);
//        }
    }
}
